﻿#include "ThreeDCloudMapWindow.h"

#include <QDebug>
#include <tuple>
#include <QSplitter>
#include <QHBoxLayout>
#include <QListWidgetItem>
#include <QTableWidgetItem>

#include <vtkPointSet.h>
#include <vtkDataSet.h>
#include <vtkRenderer.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkTextProperty.h>
#include <vtkScalarBarActor.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkStructuredGrid.h>
#include <vtkAxesActor.h>
#include <vtkFieldData.h>
#include <vtkStringArray.h>
#include <vtkScalarBarWidget.h>
#include <vtkMapper.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkDistanceToCamera.h>
#include <vtkCaptionActor2D.h>
#include <vtkProperty2D.h>
#include <vtkPolyData.h>
#include <vtkTextActor.h>
#include <vtkCubeAxesActor.h>
#include <vtkLookupTable.h>

#include "FieldGraphGenerator.h"
#include "ThreeDCloudMapSidebarSettings.h"
#include "ThreeDCloudMapSettingDialog.h"
#include "InfomationGraph3DBasical.h"
#include "PropPickerCallbackHander.h"
#include "BaseModule/IBaseSignal.h"
#include "ThreeDCloudMapSettingData.h"
#include "ThreeDCloudMapSidebarData.h"
#include "parser/jsonDef.h"
#include "NearFieldDataGenerator.h"
#include "AnimationSettingData.h"
#include "FramelessDragableTableWidget.h"
#include "ThreeDCloudMapMarkerSettingDialog.h"
#include "DataClipperGenerator.h"
#include "BaseModule/GlobalHelper.h"
#include "BaseWidget/IdaDialogMsg.h"
#include "DataManager/WindowTotalData.h"
#include "GeomtryActorGenerator.h"
#include "DataClipperFilter.h"
#include "PipelineManager.h"
#include "DataTransformFilter.h"
#include "MainWindowSignalHandler.h"
#include "BaseWidget/IWidgetSignal.h"
#include "AnimationTooBarInfoData.h"
#include "ScalarBarSettingData.h"
#include "FieldScalarBarGenerator.h"
#include "CommonFunction.h"

namespace pst
{
    ThreeDCloudMapWindow::ThreeDCloudMapWindow(QWidget* parent, int windowId)
        : Graph3DWindowBase(parent),
        m_sidebarSettings(new ThreeDCloudMapSidebarSettings(this)),
        m_mainSettingDialog(new ThreeDCloudMapSettingDialog(this)),
        //m_geometrySetting(new TDCMGeometrySettingData(this)),
        m_cubeAxesSetting(new TDCMCubeAxesActorSettingData(this)),
        m_windowId(windowId)
        //, m_isAnimationDataPrepared(false)
    {

        QHBoxLayout* layout = new QHBoxLayout(this);
        layout->setContentsMargins(0, 0, 0, 0);
        layout->setStretch(0, 1);
        layout->setStretch(1, 0);

        //QSplitter* splitter = new QSplitter(Qt::Horizontal, this);
        layout->addWidget(this->m_qvtkWidget);
        layout->addWidget(m_sidebarSettings);
        //splitter->setSizes({ 3000, 1000 });
        //layout->addWidget(splitter);

        m_sidebarSettings->setMainWiondowId(m_windowId);
        initScalarBarSettingConnection();
        initSidebarSettingConnection();

        m_mainSettingDialog->setMainWindowId(m_windowId);

        m_markerDataTable->getInnerTableWidget()->setColumnCount(5);
        QStringList nameList{ "MarkerID", "标记名", "场名", "坐标", "值" };
        m_markerDataTable->getInnerTableWidget()->setHorizontalHeaderLabels(nameList);
        m_markerDataTable->setGeometry(20, 20, 300, 120);
        m_markerDataTable->getInnerTableWidget()->setColumnHidden(0, true);
        m_markerDataTable->hide();
        // vtkNew<vtkAxesActor> axesActor;
        // m_render3D->AddActor(axesActor);

        m_doubleClickCallback = vtkSmartPointer<PropPickerCallbackHander>::New();
        this->m_renderWindow3D->GetInteractor()->AddObserver(vtkCommand::LeftButtonDoubleClickEvent, m_doubleClickCallback);

        connect(m_markerDataTable->getInnerTableWidget(), &QTableWidget::itemDoubleClicked,
            this, &ThreeDCloudMapWindow::slot_markerNameDoubleClicked);

        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::signal_getSidebarCurveDataSource,
            this, &ThreeDCloudMapWindow::slot_getSidebarCurveDataSource);

        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::signal_renameCheck, this, &ThreeDCloudMapWindow::slot_renameCheck);
        connect(m_mainSettingDialog, &ThreeDCloudMapSettingDialog::signal_checkResultNameIsValid, this, &ThreeDCloudMapWindow::slot_checkResultNameIsValid);
        connect(IWidgetSignalInstance, &BaseWidget::IWidgetSignal::signal_closeTree, this, &ThreeDCloudMapWindow::slot_closeTree);
    }

    void ThreeDCloudMapWindow::updateClipper(bool activeClipper)
    {
        for (auto info : m_graphInfoList)
        {
            if (info->m_fieldGraphGenerator == nullptr)
            {
                qDebug() << "SurfaceElectricFieldMapWindow::updateClipper info->m_fieldGraphGenerator == nullptr";
                return;
            }
            if (info->m_dataClipperFilter == nullptr)
            {
                info->m_dataClipperFilter = new DataClipperFilter();
                auto filterManager = info->m_fieldGraphGenerator->GetScalarPipelineManager();
                filterManager->AddFilter("Clipper", info->m_dataClipperFilter);
            }

            info->m_dataClipperFilter->setEnabled(activeClipper);
            info->m_dataClipperFilter->setPlaneNormalDirection(
                m_planeNormalDirection[0], m_planeNormalDirection[1], m_planeNormalDirection[2]);
            info->m_dataClipperFilter->setPlaneOrigin(
                m_planeOrigin[0], m_planeOrigin[1], m_planeOrigin[2]);

            info->m_fieldGraphGenerator->UpdateScalarFieldActor();

            auto item = info->m_sidebarItem;
            if (item == nullptr)
            {
                return;
            }
            slot_showHideItemActor(item);
        }

        updateClipperPlaneActor();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::updateClipperPlaneActor()
    {
        //生成裁剪平面的actor
        QList<vtkDataSet*> dataList;
        for (auto i : m_graphInfoList)
        {
            if (i->m_actor->GetVisibility() /*|| info->m_dataClipperGenerator->getClipActor()->GetVisibility()*/)
            {
                dataList.append(i->m_actor->GetMapper()->GetInput());
            }
            if (i->m_geomtryActorGenerator != nullptr && i->m_geomtryActorGenerator->getActor()->GetVisibility())//考虑几何
            {
                dataList.append(i->m_geomtryActorGenerator->getGeometryPolyData());
            }
        }
        //auto isSuc = this->CreateExpandedPlaneActor(actorList, m_planeNormalDirection, m_planeOrigin);
        auto isSuc = this->CreateExpandedPlaneActor(dataList, m_planeNormalDirection, m_planeOrigin);
        if (!isSuc)
        {
            return;
        }
        m_render3D->AddActor(m_clipperPlaneActor);
    }

    void ThreeDCloudMapWindow::setWindowID(int windowID)
    {
        m_windowId = windowID;
    }
    int ThreeDCloudMapWindow::getWindowID() const
    {
        return m_windowId;
    }

    void ThreeDCloudMapWindow::setWindowUniversalID(int windowUniversalID)
    {
        m_windowUniversalID = windowUniversalID;
    }
    int ThreeDCloudMapWindow::getWindowUniversalID() const
    {
        return m_windowUniversalID;
    }

    QDomElement& ThreeDCloudMapWindow::writeToProjectFile(QDomDocument* doc, QDomElement* element, bool isdiso)
    {
        QDomElement ThreeDCloudMapWindowDataRoot = doc->createElement("GraphWindow");
        QDomAttr _WindowUniversalIDattr = doc->createAttribute("WindowUniversalID");
        _WindowUniversalIDattr.setValue(QString::number(m_windowUniversalID));
        ThreeDCloudMapWindowDataRoot.setAttributeNode(_WindowUniversalIDattr);
        QDomAttr _idattr = doc->createAttribute("WindowID");
        _idattr.setValue(QString::number(m_windowId));
        ThreeDCloudMapWindowDataRoot.setAttributeNode(_idattr);
        QDomAttr typeattr = doc->createAttribute("WindowType");
        typeattr.setValue("ThreeDCloudMapWindow");
        ThreeDCloudMapWindowDataRoot.setAttributeNode(typeattr);   

        element->appendChild(ThreeDCloudMapWindowDataRoot);

        m_cubeAxesSetting->writeToProjectFile(doc, &ThreeDCloudMapWindowDataRoot, true, isdiso);
        for (auto _graphDataInfo : m_graphInfoList)
        {
            _graphDataInfo->writeToProjectFile(doc, &ThreeDCloudMapWindowDataRoot, GraphType::ThreeDCloudMap, isdiso);           
        }
        writeToProjectFile3DWindowBase(doc, &ThreeDCloudMapWindowDataRoot);

        return ThreeDCloudMapWindowDataRoot;
    }

    void ThreeDCloudMapWindow::readFromProjectFile(QDomElement* element, bool isdiso)
    {
        m_windowUniversalID = element->attribute("WindowUniversalID").toInt();
        int id = element->attribute("WindowID").toInt();
        m_windowId = id;

        auto _TDCMCubeAxesActorSettingDataFromWindowNodeList = element->elementsByTagName("TDCMCubeAxesActorSettingDataFromWindow");
        m_cubeAxesSetting->readFromProjectFile(&_TDCMCubeAxesActorSettingDataFromWindowNodeList.at(0).toElement(), true, isdiso);

        auto _infosNodeList = element->elementsByTagName("InfomationGraph3DBasical");
        auto _infosCount = _infosNodeList.count();
        if (_infosCount == 0)
            return;
        for (int i = 0; i < _infosCount; i++)
        {
            //InfomationGraph3DBasical* info = nullptr;
            QDomElement elemModel = _infosNodeList.at(i).toElement();
            auto _ProjectTreeSourceItemID = elemModel.attribute("ProjectTreeSourceItemID").toInt();
            if (_ProjectTreeSourceItemID != -1)
            {
                // 通过info的projectTreeItem到mainwindow构造完整的info信息
                auto info = MainWindowSignalHandlerInstance->BuildCompleteGraph3DInfoByProjectTreeItem(_ProjectTreeSourceItemID, GraphType::ThreeDCloudMap);
                if (info != nullptr)
                {
                    info->m_currentFrequencyIndex = elemModel.attribute("CurrentFrequencyIndex").toInt();
                    info->m_valueGroupNameIndex = elemModel.attribute("ValueGroupNameIndex").toInt();
                    info->m_valueComponentIndex = elemModel.attribute("ValueComponentIndex").toInt();

                    auto _geometryFileNameStr = elemModel.attribute("GeometryFileName");
                    info->m_geometryFileName = _geometryFileNameStr.split(";");

                    for (auto& _filePath : info->m_geometryFileName)
                    {
                        auto isSuc = GlobalHelperInstance->CurrentInstallationDirectoryPathConversion(_filePath);
                    }

                    info->m_graph = this;
                    this->addGraph3D(info);
                    info->readFromProjectFile(&elemModel, GraphType::ThreeDCloudMap, isdiso);
                    slot_updateSetting(info->m_threeDCloudMapSettingData);

                    auto _curveNameListWidget = m_sidebarSettings->getCurveNameListWidget();
                    emit IBaseSignalInstance->signal_threeDCloudMapSidebarCurveNameClicked(m_windowId, {_curveNameListWidget->row(info->m_sidebarItem)});
                    if (!info->m_TDCMSidebarData->getIsShowActor())
                        emit IBaseSignalInstance->signal_threeDCloudMapSidebarItemCheckStateChanged(m_windowId, _curveNameListWidget->row(info->m_sidebarItem), info->m_TDCMSidebarData->getIsShowActor());
                    emit IBaseSignalInstance->signal_threeDCloudMapSidebarUpdateOriginalDataSource(m_windowId,
                                                                                                   _curveNameListWidget->row(info->m_sidebarItem),
                                                                                                   info->m_TDCMSidebarData->getCurrentShowType(),
                                                                                                   info->m_TDCMSidebarData->getCurrentFixedParamIndex(),
                                                                                                   info->m_TDCMSidebarData->getIsLog(),
                                                                                                   info->m_TDCMSidebarData->getIsNormalized());

                }
            }
        }
        readFromProjectFile3DWindowBase(element);
        updateMarkerVisibility();

    }

    void ThreeDCloudMapWindow::addGraph3D(InfomationGraph3DBasical* info)
    {
        auto reader = static_cast<TextFileParser*>(info->m_reader);
        auto table = reader->getStandardTable();
        auto generator = new NearFieldDataGenerator(this);
        generator->setFileDealType(reader->getFileDealType());
        generator->setInputData(table);
        generator->setLogTheData(info->m_isLog);
        info->m_nearFieldDataGenerator = generator;

        int groupValueIndex = info->m_valueGroupNameIndex;
        int componentValueIndex = info->m_valueComponentIndex;

        int realIndex = reader->getRealValueIndex(groupValueIndex, componentValueIndex);

        bool isOk = generator->update(realIndex);
        if (!isOk)
        {
            qDebug() << " NearFieldDataGenerator update failed!";
            return;
        }
        info->m_data = generator->getOutputData();
        info->m_tableToExport = generator->getResultTable();
        m_graphInfoList.append(info);
        if(!GlobalHelperInstance->getIsOpenProject())
            info->m_informationID = WindowTotalDataInstance->getGraph3DInformationMaxID();
        WindowTotalDataInstance->appendInfomationGraph3DBasical(info);

        // 添加曲线名字到侧边栏
        //info->m_name = info->m_name + "_" + QString::number(++graphNum);
        QListWidgetItem* item = m_sidebarSettings->addData(info);
        info->m_sidebarItem = item;
        auto fieldGraphGenerator = new FieldGraphGenerator(this);
        info->m_fieldGraphGenerator = fieldGraphGenerator;
        fieldGraphGenerator->SetInputDataSet(info->m_data);
        //fieldGraphGenerator->SetScalarsScalarBarWidgetInteractor(m_renderWindow3D->GetInteractor());

        // 获取标量场和矢量场
        auto pointArray = fieldGraphGenerator->GetPointsArrayIndexAndNames();
        auto cellArray = fieldGraphGenerator->GetCellsArrayIndexAndNames();
        for (int i = 0; i < pointArray.size(); i++)
        {
            // 标量场
            m_allScalarFieldArray.push_back(pointArray[i]);
            // 矢量场
            if (pointArray[i].arrayComponent == 3)
            {
                m_allVectorFieldArray.push_back(pointArray[i]);
            }
        }
        for (int i = 0; i < cellArray.size(); i++)
        {
            // 标量场
            m_allScalarFieldArray.push_back(cellArray[i]);
            // 矢量场
            if (cellArray[i].arrayComponent == 3)
            {
                m_allVectorFieldArray.push_back(cellArray[i]);
            }
        }

        if (m_allScalarFieldArray.isEmpty())
        {
            emit IBaseSignalInstance->signal_sendErrorMessageToUI("No scalar field found!");
            return;
        }

        // 使用第一个标量场
        auto isSetSuccess = fieldGraphGenerator->SetActiveScalarAttribute(
            realIndex, FieldGraphGenerator::StructureType::POINTS, 0);
        if (!isSetSuccess)
        {
            return;
        }
        fieldGraphGenerator->UpdateScalarFieldActor();

        auto scalarDataActor = fieldGraphGenerator->GetScalarsFieldActor();
        m_render3D->AddActor(scalarDataActor);
        //auto scalarBarActor = fieldGraphGenerator->GetScalarsFieldScalarBarActor();
        //m_render3D->AddActor(scalarBarActor);
        info->m_actor = scalarDataActor;
        int _mapSettingDataID = -1;
        if (!GlobalHelperInstance->getIsOpenProject())
            _mapSettingDataID = WindowTotalDataInstance->getThreeDCloudMapMainSettingDataMaxID();
        ThreeDCloudMapSettingData* data = new ThreeDCloudMapSettingData(this, _mapSettingDataID);
        TDCMResultDataSettingData* resultDataSettingData = new TDCMResultDataSettingData(this);
        data->setResultDataSettingData(resultDataSettingData);
        //data->setGeometrySettingData(m_geometrySetting);
        data->setCubeAxesActorSettingData(m_cubeAxesSetting);

        // 设置颜色条
        auto dataType = info->m_resultType;
        auto scalarBarType = getScalarBarType(dataType);
        if (!m_scalarBarGeneratorMap.contains(scalarBarType))
        {
            m_scalarBarGeneratorMap[scalarBarType] = new FieldScalarBarGenerator(m_render3D, this);
            m_eachTypeGraphCount[scalarBarType] = 1;
            info->m_graphIDFromType = 1;
            // 创建双击事件回调
            m_doubleClickCallback->addCallbackObjectSlot(m_scalarBarGeneratorMap[scalarBarType]->getScalarBarActor(), this, "slot_scalarBarDoubleClicked");
        }
        else
        {
            m_eachTypeGraphCount[scalarBarType] += 1;
            info->m_graphIDFromType = m_eachTypeGraphCount[scalarBarType];
        }

        auto columeType = GetResultDataTypeAsString(dataType, false);

        auto scalarBarGenerator = m_scalarBarGeneratorMap[scalarBarType];
        ScalarBarSettingData* scalarBarSettingData = scalarBarGenerator->getScalarBarSettingData();
        data->setScalarBarSettingData(scalarBarSettingData);
        scalarBarSettingData->setScalarBarTitle(columeType);
        info->m_fieldScalarBarGenerator = scalarBarGenerator;

        scalarBarGenerator->addGraph(fieldGraphGenerator);
        info->m_scalarBar = scalarBarGenerator->getScalarBarActor();


        //////设置初始值 scalarBar
        //slot_scalarBarFontTypeChanged(scalarBarActor, "宋体");
        //auto titleColor = scalarBarActor->GetTitleTextProperty()->GetColor();
        //QColor color;
        //color.setRgbF(titleColor[0], titleColor[1], titleColor[2]);
        //auto range = info->m_fieldGraphGenerator->GetCurrentScalarBarRange(FieldGraphGenerator::FieldType::SCALARS);

        // TDCMScalarBarSettingData* scalarBarSettingData = new TDCMScalarBarSettingData(this);
        // TDCMResultDataSettingData* resultDataSettingData = new TDCMResultDataSettingData(this);
        // data->setScalarBarSettingData(scalarBarSettingData);
        // data->setResultDataSettingData(resultDataSettingData);

        //auto scalarBarSetting = data->getScalarBarSettingData();
        //scalarBarSetting->setScalarBarOriginalMinRange(range[0]);
        //scalarBarSetting->setScalarBarOriginalMaxRange(range[1]);
        //scalarBarSetting->setScalarBarMinValue(range[0]);
        //scalarBarSetting->setScalarBarMaxValue(range[1]);
        //scalarBarSetting->setScalarBarFontSize(24);
        //scalarBarSetting->setScalarBarIsShowTitle(true);
        //scalarBarSetting->setScalarBarTitle(scalarBarActor->GetTitle());
        //scalarBarSetting->setScalarBarTitleColor(color);
        //scalarBarActor->GetTitleTextProperty()->SetFontSize(24);

        //scalarBarActor->Modified();
        //m_dataMap.append(qMakePair(info, data));
        info->m_threeDCloudMapSettingData = data;

        //更新颜色条单位和DB
        updateDBAndUnitData();

        ////设置初始值 几何体
        if (info->m_geometryFileName.empty()) //几何路径为空
        {
            data->setGeometrySettingData(nullptr);
            info->m_geomtryActorGenerator =nullptr;
        }
        else
        {
            std::tuple<QStringList, QObject*, GeomtryActorGenerator*> existGeometryTuple;
            if (isContainGeometryPath(m_geometrySettingTupleList, info->m_geometryFileName, existGeometryTuple))
            {
                auto geometrySettingData = qobject_cast<TDCMGeometrySettingData*>(std::get<1>(existGeometryTuple));
                data->setGeometrySettingData(geometrySettingData);
                info->m_geomtryActorGenerator = std::get<2>(existGeometryTuple);
            }
            else
            {
                auto geometrySettingData = new TDCMGeometrySettingData(this);
                data->setGeometrySettingData(geometrySettingData);
                GeomtryActorGenerator* generator = new GeomtryActorGenerator(this);
                generator->setFileNameList(info->m_geometryFileName);
                generator->getActor()->SetVisibility(0);
                info->m_geomtryActorGenerator = generator;
                m_render3D->AddActor(generator->getActor());
                m_geometrySettingTupleList.append(std::make_tuple(info->m_geometryFileName, geometrySettingData, generator));
            }
        }

        // 生成侧边栏数据
        generateSidebarSettingData(item, info);
        QSignalBlocker bl(m_sidebarSettings->getCurveNameListWidget());
        item->setText(getSidebarDataFromNameItem(item)->getGraphName());
        item->setToolTip(getSidebarDataFromNameItem(item)->getGraphName());
        info->m_name = getSidebarDataFromNameItem(item)->getGraphName();

        /// 设置初始值 结果数据Actor
        auto resultDataSetting = data->getResultDataSettingData();
        resultDataSetting->setResultDataName(info->m_name);
        resultDataSetting->setResultDataTransparency(0);
        resultDataSetting->setResultDataScaleFactor(1.0);

        info->m_geometryFileName = reader->GetGeometryFileName();
        //if (m_isActiveClip)
        //{
        //    updateClipper(true);
        //}
        bool _noUse = false;
        updateClipperAndGeometry(m_isActiveClip, m_isShowingGeometry, _noUse);

        updateAnimationButtonState();
        updateCubeAxesActor(m_cubeAxesSetting->getVisibility());
        //m_render3D->ResetCamera();
        //m_renderWindow3D->Render();
        this->setCameraToIsometric();
    }

    void ThreeDCloudMapWindow::setActiveAnimation(bool active)
    {
        initAnimationInfoTextActor();
        auto widget = m_sidebarSettings->getCurveNameListWidget();
        if (m_animationType == 0) // 动数据
        {
            m_dataTimer->setInterval(1000. / m_animationSettingData->frameRate() / m_animationSpeed);

            if (!active)
            {
                m_dataTimer->stop();
                widget->setFocusPolicy(Qt::StrongFocus);
                widget->setSelectionMode(QAbstractItemView::SingleSelection);
                //m_sidebarSettings->setControlPanelEditable(true);
                connectSignalsAndSlots();
                //m_sidebarSettings->slot_curveNameClicked();

                m_sidebarSettings->setControlPlaneToAnimationState(false);
                // 清除动图数据，否则数据越存越多（因为每次开始动图都要重新生成数据
                //  （切片，归一化等数据操作必须重新从表格处执行管线））

                //m_allAnimationdData.clear(); // 只减少引用计数，不释放内存，不影响现在正在显示的actor
            }
            else
            {
                prepareAnimationData();
                m_dataTimer->start();
                widget->setFocusPolicy(Qt::NoFocus);
                widget->setSelectionMode(QAbstractItemView::NoSelection);
                //m_sidebarSettings->setControlPanelEditable(false);
                disconnectSignalsAndSlots();
                m_sidebarSettings->setControlPlaneToAnimationState(true);

                MainWindowSignalHandler::getInstance()->setToolButtonExportMotionGraphState(false);
                if (m_isExportingAnimation)
                {
                    emit IBaseSignalInstance->signal_UpdateStatusBarInformation(QStringLiteral("导出动图正在进行中..."), true);
                    QCoreApplication::processEvents();
                }
            }
        }

        else if (m_animationType == 1) // 动相机
        {
            if (!active)
            {
                m_cameraTimer->stop();
                //m_sidebarSettings->setControlPanelEditable(true);
                widget->setFocusPolicy(Qt::StrongFocus);
                widget->setSelectionMode(QAbstractItemView::SingleSelection);
                connectSignalsAndSlots();
                m_sidebarSettings->setControlPlaneToAnimationState(false);

            }
            else
            {
                m_animationCameraAngle = 0.0;
                m_animationCameraCount = 0;
                m_cameraTimer->start();
                //m_sidebarSettings->setControlPanelEditable(false);
                widget->setFocusPolicy(Qt::NoFocus);
                widget->setSelectionMode(QAbstractItemView::NoSelection);
                disconnectSignalsAndSlots();
                m_sidebarSettings->setControlPlaneToAnimationState(true);

                MainWindowSignalHandler::getInstance()->setToolButtonExportMotionGraphState(false);
                if (m_isExportingAnimation)
                {
                    emit IBaseSignalInstance->signal_UpdateStatusBarInformation(QStringLiteral("导出动图正在进行中..."), true);
                    QCoreApplication::processEvents();
                }
            }
        }
        m_animationInfoTextActor->SetVisibility(active);
        emit IWidgetSignalInstance->signal_setShowAnimationTextWidget(active);

        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::exportAnimationData(const QString& path)
    {
        m_isExportingAnimation = true;
        m_loopCount = 0;
        m_animationImageList.clear();
        m_exportAnimationPath = path;
        m_isBeginExportAnimation = true;
        if (m_animationType == 0) // 动数据
        {
            prepareAnimationData();
            setActiveAnimation(true);

            for (auto info : m_graphInfoList)
            {
                info->m_lastFrameIndexBeforeExportAnimation = info->m_currentAnimationIndex;
            }
        }
        else if (m_animationType == 1) // 动相机
        {
            setActiveAnimation(true);
        }
    }

    void ThreeDCloudMapWindow::exportSourceDataToLocal()
    {
        QString filter = QObject::tr("CSV Files (*.csv);;Text Files (*.txt)");
        // 打开文件保存对话框，若用户在对话框中选择了文件，则返回对应的文件名
        QString fileName = QFileDialog::getSaveFileName(nullptr,
            QObject::tr("保存文件"),
            "",
            filter);

        // 如果选择为空，则用户可能取消了操作
        if (fileName.isEmpty())
            return;

        auto _isOK = processAndWriteTables(m_graphInfoList, fileName);
        if (_isOK)
        {
            auto _res = IdaDialogMsg::showDialog(nullptr, QStringLiteral("导出数据成功！"), EDialogMsg::Normal, QStringLiteral("成功"), {QStringLiteral("确定")});
            QString tmp = "\"" + fileName + "\"";
            QString pyCode = QString("PostProcessing.exportData(%1)").arg(tmp);
            emit IBaseSignalInstance->signal_execPYCode(QStringList{pyCode}, true, false);
        }
        else
            IBaseSignalInstance->signal_sendErrorMessageToUI("导出数据失败");
    }

    void ThreeDCloudMapWindow::pyExportSourceDataToLocal(QString parms)
    {
        processAndWriteTables(m_graphInfoList, parms);
    }

    bool ThreeDCloudMapWindow::processAndWriteTables(QList<InfomationGraph3DBasical*> infoList, const QString& outputFilename)
    {
        QFile file(outputFilename);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            qDebug() << "Unable to open file " << outputFilename;
            return false;
        }

        QTextStream out(&file);

        // 遍历每个 table
        for (int i = 0; i < infoList.size(); ++i)
        {
            auto info = infoList[i];
            vtkTable* table = info->m_tableToExport;

            //double frequency = info->m_currentFrequency;
            int valueIndex = info->m_valueGroupNameIndex;

            // 提取 HeadComment 字段内容，作为该 table 的第一行输出
            vtkStringArray* headCommentArray = vtkStringArray::SafeDownCast(table->GetFieldData()->GetAbstractArray("HeadComment"));
            if (!headCommentArray || headCommentArray->GetNumberOfValues() == 0)
            {
                qDebug() << "Table " << i << " has no ‘HeadComment’.";
                continue;
            }
            QString headComment = QString::fromStdString(headCommentArray->GetValue(0));
            out << headComment << "\n";

            // 提取表格Header
            vtkStringArray* headerArray = vtkStringArray::SafeDownCast(table->GetFieldData()->GetAbstractArray("Header"));
            if (!headerArray || headerArray->GetNumberOfValues() == 0)
            {
                qDebug() << "Table " << i << " has no 'headerArray'.";
                continue;
            }
            QString header = QString::fromStdString(headerArray->GetValue(0));
            QString frequencyStr = header.section(',', 0, 0).trimmed();

            // 生成新的 processedTable：先插入 Frequency 列
            vtkSmartPointer<vtkTable> processedTable = vtkSmartPointer<vtkTable>::New();
            // vtkSmartPointer<vtkDoubleArray> frequencyColumn = vtkSmartPointer<vtkDoubleArray>::New();
            // frequencyColumn->SetName(frequencyStr.toStdString().c_str());
            // vtkIdType numRows = table->GetNumberOfRows();
            // frequencyColumn->SetNumberOfTuples(numRows);
            // for (vtkIdType row = 0; row < numRows; ++row)
            //{
            //     frequencyColumn->SetValue(row, frequency);
            // }
            // processedTable->AddColumn(frequencyColumn);

            for (int colIndex = 0; colIndex < 3; ++colIndex)
            {
                if (colIndex < table->GetNumberOfColumns())
                {
                    vtkAbstractArray* col = table->GetColumn(colIndex);
                    processedTable->AddColumn(col);
                }
            }
            // 添加原 table 的第2 + valueIndex列，需确保列数足够
            if (table->GetNumberOfColumns() > 3 + valueIndex)
            {
                vtkAbstractArray* col = table->GetColumn(3 + valueIndex);
                processedTable->AddColumn(col);
            }
            else
            {
                qDebug() << "Table col number is not enough!";
            }

            // 写入表头（列名称），列之间使用逗号分隔
            QStringList headers;
            for (int col = 0; col < processedTable->GetNumberOfColumns(); ++col)
            {
                QString colName = QString::fromStdString(processedTable->GetColumnName(col));
                if (col == 0)
                {
                    colName = "# " + colName;
                }
                headers << colName;
            }
            out << headers.join(",") << "\n";

            // 写入数据行，每行数据各字段间以逗号分隔
            for (vtkIdType row = 0; row < processedTable->GetNumberOfRows(); ++row)
            {
                QStringList rowValues;
                for (int col = 0; col < processedTable->GetNumberOfColumns(); ++col)
                {
                    vtkVariant val = processedTable->GetValue(row, col);
                    rowValues << QString::fromStdString(val.ToString());
                }
                out << rowValues.join(",") << "\n";
            }

            // 每个 table 输出完后增加两行空白（用于区分不同的 table）
            if (i < infoList.size() - 1)
            {
                out << "\n\n";
            }
        }
        return true;
    }

    void ThreeDCloudMapWindow::addAMarkerDataToPickedDataDisplayWindow(Marker3DDataInfo* info)
    {
        int count = 0;
        int row = m_markerDataTable->getInnerTableWidget()->rowCount();
        m_markerDataTable->getInnerTableWidget()->insertRow(row);
        m_markerDataTable->getInnerTableWidget()->setItem(row, count++, new QTableWidgetItem(QString::number(info->m_markerId)));
        m_markerDataTable->getInnerTableWidget()->setItem(row, count++, new QTableWidgetItem(info->m_markerName));
        m_markerDataTable->getInnerTableWidget()->setItem(row, count++, new QTableWidgetItem(info->m_fieldName));
        QString markerPosition = "(" + QString::number(info->m_markerPosition[0]) + "," + QString::number(info->m_markerPosition[1]) + "," + QString::number(info->m_markerPosition[2]) + ")";
        m_markerDataTable->getInnerTableWidget()->setItem(row, count++, new QTableWidgetItem(markerPosition));
        m_markerDataTable->getInnerTableWidget()->setItem(row, count++, new QTableWidgetItem(info->m_markerValue));
        updatePickedDataDisplayWindowVisibility();

        // 记录该actor此时的显示类别和固定值参数
        for (auto graphInfo : m_graphInfoList)
        {
            if (graphInfo->m_actor == info->m_sourceActor)
            {
                auto curveNameWidgetItem = graphInfo->m_sidebarItem;
                auto sideBarData = getSidebarDataFromNameItem(curveNameWidgetItem);
                if (sideBarData != nullptr)
                {
                    if (!GlobalHelperInstance->getIsOpenProject())
                    {
                        info->m_showType = sideBarData->getCurrentShowType();
                        info->m_fixedParamIndex = sideBarData->getCurrentFixedParamIndex();
                    }
                }
            }
        }
    }

    void ThreeDCloudMapWindow::pyCurveNameClicked(QList<int> selectedIndexs)
    {
        m_sidebarSettings->pyCurveNameClicked(selectedIndexs);
    }

    void ThreeDCloudMapWindow::pyUpdateFixedParameter(int index)
    {
        m_sidebarSettings->pyUpdateFixedParameter(index);
    }

    void ThreeDCloudMapWindow::pyUpdateOriginalDataSource(int index, int showType, int fixedValueIndex, bool isLog, bool isNormalize)
    {
        m_sidebarSettings->pyUpdateOriginalDataSource(index, showType, fixedValueIndex, isLog, isNormalize);
    }

    void ThreeDCloudMapWindow::pyResultDataChanged(int index)
    {
        m_sidebarSettings->pyResultDataChanged(index);
    }

    void ThreeDCloudMapWindow::pyNameItemRename(int itemIndex, QString newName)
    {
        auto listWidget = m_sidebarSettings->getCurveNameListWidget();
        QListWidgetItem* item = listWidget->item(itemIndex);
        QString curText = item->text();
        item->setText(newName);
    }

    void ThreeDCloudMapWindow::pyDelete3DCloudMap(QString selectedIndexs)
    {
        m_sidebarSettings->pyDelete3DCloudMap(selectedIndexs);
    }

    void ThreeDCloudMapWindow::pyDataOprationChanged(bool isLoged, bool isNormalized)
    {
        m_sidebarSettings->pyDataOprationChanged(isLoged, isNormalized);
    }

    void ThreeDCloudMapWindow::pyItemCheckStateChanged(int itemIndex, bool visible)
    {
        m_sidebarSettings->pyItemCheckStateChanged(itemIndex, visible);
    }

    void ThreeDCloudMapWindow::pySaveThreeDCloudMapMainSettingData(int type, int settingDataId,
        bool scalarBarIsAutoRange, double scalarBarMin, double scalarBarMax,
        bool scalarBarIsShowTitle, QString scalarBarTitle, QString scalarBarFontColor, int scalarBarFontSize,
        int geometryTransparency, QString resultGraphName, int resultGraphModelTransparency, bool cubeAxesIsVisible)
    {
        for (auto i : m_graphInfoList)
        {
            if (i->m_threeDCloudMapSettingData->getID() == settingDataId)
            {
                QList<int> _scalarBarFontColor = GlobalHelperInstance->convertStringToIntList(scalarBarFontColor);
                QColor color(_scalarBarFontColor[0], _scalarBarFontColor[1], _scalarBarFontColor[2]);

                auto data = i->m_threeDCloudMapSettingData;
                data->getScalarBarSettingData()->setScalarBarAutoRange(scalarBarIsAutoRange);
                data->getScalarBarSettingData()->setScalarBarMinValue(scalarBarMin);
                data->getScalarBarSettingData()->setScalarBarMaxValue(scalarBarMax);
                data->getScalarBarSettingData()->setScalarBarIsShowTitle(scalarBarIsShowTitle);
                data->getScalarBarSettingData()->setScalarBarTitle(scalarBarTitle);
                data->getScalarBarSettingData()->setScalarBarTitleColor(color);
                data->getScalarBarSettingData()->setScalarBarFontSize(scalarBarFontSize);

                if (data->getGeometrySettingData())
                {
                    data->getGeometrySettingData()->setGeometryTransparency(geometryTransparency);
                }

                data->getResultDataSettingData()->setResultDataName(resultGraphName);
                data->getResultDataSettingData()->setResultDataTransparency(resultGraphModelTransparency);

                if (data->getCubeAxesActorSettingData())
                {
                    data->getCubeAxesActorSettingData()->setVisibility(cubeAxesIsVisible);
                }

                slot_updateSetting(data);
                m_mainSettingDialog->setType((pst::ThreeDCloudMapSettingDialog::EntryType)type);
            }
        }
    }

    void ThreeDCloudMapWindow::slot_scalarBarDoubleClicked(vtkProp* pickedProp)
    { // 使用 pickedProp 进行处理
        emit IWidgetSignalInstance->signal_exitAddMarkerState();
        if (pickedProp == nullptr)
        {
            return;
        }

        // 只有一个数据
        if (m_graphInfoList.size() == 1)
        {
            if (m_graphInfoList[0]->m_scalarBar == pickedProp)
            {

                auto tmp = m_graphInfoList[0]->m_fieldScalarBarGenerator->getLookupTable()->GetRange();
                m_graphInfoList[0]->m_threeDCloudMapSettingData->getScalarBarSettingData()->setScalarBarMinValue(tmp[0]);
                m_graphInfoList[0]->m_threeDCloudMapSettingData->getScalarBarSettingData()->setScalarBarMaxValue(tmp[1]);
                m_mainSettingDialog->updateSettingDataToUI(m_graphInfoList[0]->m_threeDCloudMapSettingData, ThreeDCloudMapSettingDialog::EntryType::ScalarBar);
            }
        }
        // 多个数据
        else
        {
            ThreeDCloudMapSettingData* currentData = nullptr;
            for (const auto& i : m_graphInfoList)
            {
                if (i->m_scalarBar == pickedProp)
                {
                    currentData = i->m_threeDCloudMapSettingData;
                    auto tmp = i->m_fieldScalarBarGenerator->getLookupTable()->GetRange();
                    i->m_threeDCloudMapSettingData->getScalarBarSettingData()->setScalarBarMinValue(tmp[0]);
                    i->m_threeDCloudMapSettingData->getScalarBarSettingData()->setScalarBarMaxValue(tmp[1]);
                    //m_mainSettingDialog->updateSettingDataToUI(i.second, ThreeDCloudMapSettingDialog::EntryType::ScalarBar);
                }
            }

            if (isGeometryPathAllSame(m_graphInfoList)) //几何路径全相同
            {
                ThreeDCloudMapSettingData* tempData = new ThreeDCloudMapSettingData(this, -1);
                tempData->setScalarBarSettingData(currentData->getScalarBarSettingData());
                tempData->setGeometrySettingData(currentData->getGeometrySettingData());
                tempData->setResultDataSettingData(nullptr);
                tempData->setCubeAxesActorSettingData(currentData->getCubeAxesActorSettingData());

                m_mainSettingDialog->updateSettingDataToUI(tempData, ThreeDCloudMapSettingDialog::EntryType::ScalarBar);
            }
            else //几何路径不全相同
            {
                ThreeDCloudMapSettingData* tempData = new ThreeDCloudMapSettingData(this, -1);
                tempData->setScalarBarSettingData(currentData->getScalarBarSettingData());
                tempData->setGeometrySettingData(nullptr);
                tempData->setResultDataSettingData(nullptr);
                tempData->setCubeAxesActorSettingData(currentData->getCubeAxesActorSettingData());

                m_mainSettingDialog->updateSettingDataToUI(tempData, ThreeDCloudMapSettingDialog::EntryType::ScalarBar);
            }
        }

        m_mainSettingDialog->execWindow();
    }

    void ThreeDCloudMapWindow::updateDBAndUnitData()
    {
        QSet<int> typeProcessed;
        for (auto i : m_graphInfoList)
        {
            auto info = i;

            //以侧边栏同类型的第一个数据为准
            if (typeProcessed.contains(info->m_resultType))
            {
                continue;
            }
            typeProcessed.insert(info->m_resultType);

            auto reader = static_cast<TextFileParser*>(info->m_reader);

            int groupValueIndex = info->m_valueGroupNameIndex;
            int componentValueIndex = info->m_valueComponentIndex;
            int realIndex = reader->getRealValueIndex(groupValueIndex, componentValueIndex);
            auto meta = reader->getDataInfoByRealValueIndex(realIndex);
            auto unit = meta.unit;//单位
            unit.toUpper() == "NONE" ? unit = "" : unit;

            auto nearFieldDataGenerator = info->m_nearFieldDataGenerator;
            auto isLog = nearFieldDataGenerator->getLogTheData();

            auto sliderBarSettingData = i->m_threeDCloudMapSettingData->getScalarBarSettingData();
            sliderBarSettingData->setScalarBarUnit(unit);
            sliderBarSettingData->setScalarBarIsLog(isLog);
        }
    }

    void ThreeDCloudMapWindow::initScalarBarSettingConnection()
    {
        connect(m_mainSettingDialog, &ThreeDCloudMapSettingDialog::signal_updateSetting,
            this, &ThreeDCloudMapWindow::slot_updateSetting);
    }

    void ThreeDCloudMapWindow::initSidebarSettingConnection()
    {
        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::siganl_showHideItemActor,
            this, &ThreeDCloudMapWindow::slot_showHideItemActor);
        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::siganl_graphNameDoubleClicked,
            this, &ThreeDCloudMapWindow::slot_graphNameDoubleClicked);
        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::signal_chosenItemsChanged,
            this, &ThreeDCloudMapWindow::slot_chosenItemsChanged);
        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::signal_updateActorValue,
            this, &ThreeDCloudMapWindow::slot_updateActorValue);
        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::signal_updateOrignalData,
            this, &ThreeDCloudMapWindow::slot_updateOriginalData);
        connect(m_sidebarSettings, &ThreeDCloudMapSidebarSettings::signal_deleteChosenGraphs,
            this, &ThreeDCloudMapWindow::slot_deleteChosenGraphs);
    }
    void ThreeDCloudMapWindow::slot_chosenItemsChanged(const QList<QListWidgetItem*>& itemList)
    {
        ThreeDCloudMapSidebarData* data = getSidebarDataFromNameItem(itemList.at(0));
        // data->PrintSelf();
        m_sidebarSettings->updateInfoDataAndInterfaceToUI(data);
    }

    void ThreeDCloudMapWindow::slot_updateActorValue(ThreeDCloudMapSidebarData* data)
    {
        auto info = getGraph3DInfoFromSidebarData(data);
        auto item = info->m_sidebarItem;
        info->m_valueGroupNameIndex = data->getCurrentValueGroupNameIndex();
        info->m_valueComponentIndex = data->getCurrentComponentIndex();

        int groupValueIndex = info->m_valueGroupNameIndex;
        int componentValueIndex = info->m_valueComponentIndex;

        auto reader = static_cast<TextFileParser*>(info->m_reader);
        int realIndex = reader->getRealValueIndex(groupValueIndex, componentValueIndex);

        auto fieldGraphGenerator = info->m_fieldGraphGenerator;
        if (fieldGraphGenerator == nullptr)
        {
            qDebug() << "Error: " << __FILE__ << " " << __LINE__ << " Chosen data's generator not exist!";
            return;
        }
        auto isSetSuccess = fieldGraphGenerator->SetActiveScalarAttribute(
            realIndex, FieldGraphGenerator::StructureType::POINTS, 0);

        if (!isSetSuccess)
        {
            qDebug() << "Error: " << __FILE__ << " " << __LINE__ << " Set active scalar attribute failed!";
            return;
        }

        //for (auto i : m_dataMap)
        //{
        //    if (i.first == info)
        //    {
        //        auto mainSettingData = i.second;
        //        auto scalarBarSetting = mainSettingData->getScalarBarSettingData();
        //        auto range = fieldGraphGenerator->GetCurrentScalarBarRange(FieldGraphGenerator::FieldType::SCALARS);
        //        scalarBarSetting->setScalarBarOriginalMinRange(range[0]);
        //        scalarBarSetting->setScalarBarOriginalMaxRange(range[1]);

        //        if (scalarBarSetting->getScalarBarAutoRange())
        //        {
        //            fieldGraphGenerator->SetScalarBarRange(range[0], range[1], FieldGraphGenerator::FieldType::SCALARS);
        //        }
        //        else
        //        {
        //            auto currentMin = scalarBarSetting->getScalarBarMinValue();
        //            auto currentMax = scalarBarSetting->getScalarBarMaxValue();
        //            fieldGraphGenerator->SetScalarBarRange(currentMin, currentMax, FieldGraphGenerator::FieldType::SCALARS);
        //        }
        //    }
        //}

        if (!info->m_isGraphRenamed)
        {
            auto name = generateGraphNameAuto(info);
            QSignalBlocker bl(m_sidebarSettings->getCurveNameListWidget());
            item->setText(name);
            item->setToolTip(name);

            info->m_name = name;

            for (auto i : m_graphInfoList)
            {
                if (i == info)
                {
                    i->m_threeDCloudMapSettingData->getResultDataSettingData()->setResultDataName(name);
                }
            }
        }

        updateMarkerValue();
        updateDBAndUnitData();
        updateDataActorPickable();
        updateClipper(true);

        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_updateOriginalData(ThreeDCloudMapSidebarData* data)
    {
        emit IWidgetSignalInstance->signal_exitAddMarkerState();
        InfomationGraph3DBasical* info = getGraph3DInfoFromSidebarData(data);
        // 添加nullptr判断，避免程序崩溃问题。
        if (info == nullptr)
        {
            qDebug() << "InfomationGraph3DBasical* info = getGraph3DInfoFromSidebarData(data)为nullptr." << endl;
            return;
        }
        auto item = info->m_TDCMSidebarData;
        ThreeDCloudMapSettingData* mainSettingData = nullptr;
        for (auto i : m_graphInfoList)
        {
            if (i == info)
            {
                mainSettingData = i->m_threeDCloudMapSettingData;
            }
        }
        if (mainSettingData == nullptr)
        {
            qDebug() << "Error: " << __FILE__ << " " << __LINE__ << " Chosen data's main setting data not exist!";
            return;
        }
        auto scalarBarSetting = mainSettingData->getScalarBarSettingData();

        auto nearFieldDataGenerator = info->m_nearFieldDataGenerator;
        auto fieldGraphGenerator = info->m_fieldGraphGenerator;
        info->m_valueGroupNameIndex = data->getCurrentValueGroupNameIndex();

        auto showType = data->getCurrentShowType();
        auto slicePositionIndex = data->getCurrentFixedParamIndex();

        switch (showType)
        {
        case 0:
            nearFieldDataGenerator->setDataExtraction(-1, slicePositionIndex);
            break;

        case 1: // xoy
        {
            nearFieldDataGenerator->setDataExtraction(2, slicePositionIndex);
            break;
        }

        case 2: // yoz
        {
            nearFieldDataGenerator->setDataExtraction(0, slicePositionIndex);
            break;
        }

        case 3: // zox
        {
            nearFieldDataGenerator->setDataExtraction(1, slicePositionIndex);
            break;
        }

        default:
            break;
        }

        auto valueIndex = data->getCurrentValueGroupNameIndex();
        auto parser = data->getTextFileParser();
        auto compIndex = data->getCurrentComponentIndex();

        int realIndex = parser->getRealValueIndex(valueIndex, compIndex);
        auto meta = parser->getDataInfoByRealValueIndex(realIndex);
        bool _isLog = false;
        if (meta.resultDataType == 2 || meta.resultDataType == 4)//幅度或标量采用界面设置的log
        {
            _isLog = data->getIsLog();
        }

        nearFieldDataGenerator->setLogTheData(_isLog);
        nearFieldDataGenerator->setNormalizeTheData(data->getIsNormalized());

        nearFieldDataGenerator->update(realIndex);
        info->m_data = nearFieldDataGenerator->getOutputData();
        info->m_tableToExport = nearFieldDataGenerator->getResultTable();

        fieldGraphGenerator->SetInputDataSet(nearFieldDataGenerator->getOutputData());
        auto isSetSuccess = fieldGraphGenerator->SetActiveScalarAttribute(
            realIndex, FieldGraphGenerator::StructureType::POINTS, 0);
        fieldGraphGenerator->UpdateScalarFieldActor();
        fieldGraphGenerator->GetScalarsFieldActor()->SetVisibility(data->getIsShowActor());
        info->m_actor = fieldGraphGenerator->GetScalarsFieldActor();

        //auto isSetSuccess = fieldGraphGenerator->SetActiveScalarAttribute(
        //    realIndex, FieldGraphGenerator::StructureType::POINTS, 0);

        if (!isSetSuccess)
        {
            qDebug() << "Error: " << __FILE__ << " " << __LINE__ << " Set active scalar attribute failed!";
            return;
        }

        if (info->m_actor == nullptr)
        {
            return;
        }

        auto range = fieldGraphGenerator->GetActiveFieldOriginalRange();
        scalarBarSetting->setScalarBarOriginalMinRange(range[0]);
        scalarBarSetting->setScalarBarOriginalMaxRange(range[1]);

        updateDBAndUnitData();
        slot_updateSetting(mainSettingData);

        updateMarkerVisibility();
        updateMarkerValue(); // 必须先更新可见性，再更数值

        //m_render3D->ResetCamera();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_deleteChosenGraphs(const QList<QListWidgetItem*>& itemList)
    {
        auto curveNameWidget = m_sidebarSettings->getCurveNameListWidget();
        for (QListWidgetItem* item : itemList)
        {
            auto _infoID = getInfoFromSidebarNameItem(item)->m_informationID;
            WindowTotalDataInstance->removeInfomationGraph3DBasicalByID(_infoID);
            //m_sideBarSettingData.remove(item);

            int row = curveNameWidget->row(item);
            if (row != -1)
            {
                m_sidebarSettings->clearControlPlane();//先清除再删除，删除会触发slot_curveNameClicked
                delete curveNameWidget->takeItem(row);
            }
        }

        for (const auto& item : itemList)
        {
            if (item == nullptr)
                return;
            InfomationGraph3DBasical* info = getInfoFromSidebarNameItem(item);

            int count = 0;
            for (const auto& i : m_graphInfoList)
            {
                if (i->m_geometryFileName == info->m_geometryFileName)
                {
                    count++;
                }
            }

            if (count < 2)//是该路径的唯一一个几何体
            {
                if (info->m_geomtryActorGenerator != nullptr)//删除几何体
                {
                    m_render3D->RemoveActor(info->m_geomtryActorGenerator->getActor());

                    //清除设置
                    for(int i = m_geometrySettingTupleList.size()-1; i >= 0; --i)
                    {
                        if(std::get<0>(m_geometrySettingTupleList[i]) == info->m_geometryFileName)
                        {
                            m_geometrySettingTupleList.removeAt(i);
                        }
                    }
                }
            }
 
            removeActorWithMarker(info);
            m_graphInfoList.removeOne(info);

            //for (auto i : m_dataMap)
            //{
            //    if (i.first == info)
            //    {
            //        m_dataMap.removeOne(i);
            //        break;
            //    }
            //}
        }

        updateClipperPlaneActor();
        //m_sidebarSettings->clearControlPlane();
        updateModelDisplayAndClipperButtonCheckState();
        updateAnimationButtonState();//放在updateModelDisplayAndClipperButtonCheckState之后
        updateDBAndUnitData();
        updateCubeAxesActor(m_cubeAxesSetting->getVisibility());
        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_markerNameDoubleClicked(QTableWidgetItem* item)
    {
        emit IWidgetSignalInstance->signal_exitAddMarkerState();
        if (item == nullptr)
        {
            return;
        }

        auto row = m_markerDataTable->getInnerTableWidget()->row(item);
        if (row == -1)
        {
            return;
        }

        int markerId = m_markerDataTable->getInnerTableWidget()->item(row, 0)->text().toInt();
        auto markerInfo = m_marker3DDataInfoList.value(markerId);

        ThreeDCloudMapMarkerSettingDialog* dialog = new ThreeDCloudMapMarkerSettingDialog(this);
        dialog->updateMarker3DDataInfo(markerInfo);

        QHash<int, QString> map = getMarkerNameMap();
        for (auto it = map.cbegin(); it != map.cend(); ++it)
        {
            if (it.value() == m_markerDataTable->getInnerTableWidget()->item(row, 1)->text())
            {
                dialog->setCurrentMarkerIndex(it.key());
                break;
            }
        }
        dialog->setExistMarkerMap(map);
        dialog->showWindow();

        connect(dialog, &ThreeDCloudMapMarkerSettingDialog::signal_marker3DDataInfoChanged,
            this, &ThreeDCloudMapWindow::slot_marker3DDataInfoChanged);
        // m_mainSettingDialog->updateSettingDataToUI(info, ThreeDCloudMapSettingDialog::EntryType::ResultData);
        // m_mainSettingDialog->execWindow();
    }

    void ThreeDCloudMapWindow::slot_marker3DDataInfoChanged(Marker3DDataInfo* marker3DDataInfo)
    {
        auto markerName = marker3DDataInfo->m_markerName;
        auto markerSize = marker3DDataInfo->m_markerSize;
        auto markerTextFontSize = marker3DDataInfo->m_markerTextFontSize;
        auto distanceToCamera = marker3DDataInfo->m_distanceToCamera;

        if (distanceToCamera == nullptr)
        {
            return;
        }

        vtkSmartPointer<vtkActor> markerActor = marker3DDataInfo->m_markerActor;
        vtkSmartPointer<vtkCaptionActor2D> markerTextActor = marker3DDataInfo->m_markerTextActor;

        distanceToCamera->SetScreenSize(markerSize);
        markerActor->Modified();

        vtkTextProperty* textProp = markerTextActor->GetCaptionTextProperty();
        textProp->SetFontSize(markerTextFontSize);
        markerTextActor->SetCaption(markerName.toStdString().c_str());
        markerTextActor->Modified();

        auto markerTable = m_markerDataTable->getInnerTableWidget();
        for (int row = 0; row < markerTable->rowCount(); ++row)
        {
            if (markerTable->item(row, 0)->text().toInt() == marker3DDataInfo->m_markerId)
            {
                markerTable->item(row, 1)->setText(markerName);
                break;
            }
        }

        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_scalarBarFontTypeChanged(vtkScalarBarActor* scalarBarActor, QString fontType)
    {
        if (scalarBarActor == nullptr)
        {
            return;
        }
        if (fontType == "微软雅黑") // 并非真正的微软雅黑
        {
            QString currenEXEPath = QCoreApplication::applicationDirPath();
            auto micFont = currenEXEPath + "/Fonts/Alibaba-PuHuiTi-Regular.ttf";
            scalarBarActor->GetTitleTextProperty()->SetFontFamily(VTK_FONT_FILE);
            scalarBarActor->GetTitleTextProperty()->SetFontFile(micFont.toLocal8Bit());
        }
        else if (fontType == "宋体") // 并非真正的宋体
        {
            QString currenEXEPath = QCoreApplication::applicationDirPath();
            auto songFont = currenEXEPath + "/Fonts/TangXianBinSong-2.otf";
            scalarBarActor->GetTitleTextProperty()->SetFontFamily(VTK_FONT_FILE);
            scalarBarActor->GetTitleTextProperty()->SetFontFile(songFont.toLocal8Bit());
        }
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_updateSetting(ThreeDCloudMapSettingData* data)
    {
        //几何
        auto _geometrySettingData = data->getGeometrySettingData();
        if (_geometrySettingData != nullptr)
        {
            for (const auto& i : m_graphInfoList)
            {
                if (i->m_threeDCloudMapSettingData->getGeometrySettingData() == _geometrySettingData)
                {
                    auto info = i;
                    auto _geometryTransparency = _geometrySettingData->getGeometryTransparency();
                    if (info->m_geomtryActorGenerator != nullptr)
                    {
                        info->m_geomtryActorGenerator->getActor()->GetProperty()->SetOpacity(1 - _geometryTransparency / 100.);
                        if (_geometryTransparency == 100)
                        {
                            info->m_geomtryActorGenerator->getActor()->VisibilityOff();
                        }
                        else
                        {
                            info->m_geomtryActorGenerator->getActor()->SetVisibility(m_isShowingGeometry);
                        }
                    }
                    break;
                }
            }
        }

        //结果
        auto _resultSettingData = data->getResultDataSettingData();
        if (_resultSettingData != nullptr)
        {
            for (const auto& i : m_graphInfoList)
            {
                if (i->m_threeDCloudMapSettingData->getResultDataSettingData() == _resultSettingData)
                {
                    auto info = i;
                    auto _actorName = _resultSettingData->getResultDataName();
                    auto _transparency = _resultSettingData->getResultDataTransparency();
                    auto _scaleFactor = _resultSettingData->getResultDataScaleFactor();

                    info->m_actor->GetProperty()->SetOpacity(1 - _transparency / 100.);
                    if (_transparency == 100)
                    {
                        info->m_actor->VisibilityOff();
                    }
                    else
                    {
                        auto visbility = info->m_sidebarItem->checkState();
                        info->m_actor->SetVisibility(visbility);
                    }
                    //info->m_actor->SetScale(_scaleFactor);
                    synchronousActorName(info, _actorName);
                    break;
                }
            }

        }

        //包围盒
        if (data->getCubeAxesActorSettingData())
        {
            updateCubeAxesActor(data->getCubeAxesActorSettingData()->getVisibility());
        }

        updateClipperPlaneActor();
        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();

        // 将颜色条数据回写到对话框
        auto _scalarBarSettingData = data->getScalarBarSettingData();
        if (_scalarBarSettingData != nullptr)
        {
            for (const auto& i : m_graphInfoList)
            {
                if (i->m_threeDCloudMapSettingData->getScalarBarSettingData() == _scalarBarSettingData)
                {
                    auto info = i;
                    auto tmp = info->m_fieldScalarBarGenerator->getLookupTable()->GetRange();
                    m_mainSettingDialog->setScalarBarCustomRange(tmp[0], tmp[1]);
                }
            }
        }

    }

    void ThreeDCloudMapWindow::slot_showHideItemActor(QListWidgetItem* item)
    {
        if (item == nullptr)
            return;
        InfomationGraph3DBasical* info = getInfoFromSidebarNameItem(item);
        if (info == nullptr) return;

        FieldGraphGenerator* fieldGraphGenerator = info->m_fieldGraphGenerator;
        auto data = info->m_TDCMSidebarData;
        if (fieldGraphGenerator == nullptr)
        {
            qDebug() << "Error: " << __FILE__ << " " << __LINE__ << " Chosen data's generator not exist!";
            return;
        }
        auto dataActor = fieldGraphGenerator->GetScalarsFieldActor();

        auto checkState = item->checkState() == Qt::Checked ? true : false;
        data->setIsShowActor(checkState);
        bool markerState = false;

        info->m_fieldGraphGenerator->GetScalarsFieldActor()->SetVisibility(checkState);

        bool isSameTypeAllHide = true;
        for (auto i : m_graphInfoList)
        {
            //判断类型是否相同
            if (info->m_resultType == i->m_resultType)
            {
                if (i->m_fieldGraphGenerator->GetScalarsFieldActor()->GetVisibility())
                {
                    isSameTypeAllHide = false;
                    break;
                }
            }
        }

        info->m_fieldScalarBarGenerator->getScalarBarActor()->SetVisibility(!isSameTypeAllHide);
        info->m_fieldScalarBarGenerator->getScalarBarWidget()->SetEnabled(!isSameTypeAllHide);

        //// 更新数据actor是否显示
        //markerState = m_isActiveClip ? false : checkState;

        //int hideCount = 0;
        //auto innerMatrkerTable = m_markerDataTable->getInnerTableWidget();
        //for (const auto& i : m_marker3DDataInfoList)
        //{
        //    if (i->m_sourceActor == dataActor)
        //    {
        //        // 同步标记actor可见性
        //        i->m_markerActor->SetVisibility(markerState);
        //        i->m_markerTextActor->SetVisibility(markerState);

        //        // 同步markerTable可见性
        //        for (int row = 0; row < innerMatrkerTable->rowCount(); ++row)
        //        {
        //            if (innerMatrkerTable->item(row, 0)->text().toInt() == i->m_markerId)
        //            {
        //                innerMatrkerTable->setRowHidden(row, !markerState);
        //                hideCount++;
        //            }
        //        }
        //    }
        //}

        //// 判断是否全部隐藏，如果是，隐藏标记表格
        //bool isAllHide = true;
        //for (int row = 0; row < innerMatrkerTable->rowCount(); ++row)
        //{
        //    if (!innerMatrkerTable->isRowHidden(row))
        //    {
        //        isAllHide = false;
        //        break;
        //    }
        //}
        //isAllHide ? m_markerDataTable->hide() : m_markerDataTable->show();

        updateClipperPlaneActor();
        updateMarkerVisibility();
        updateMarkerValue(); // 必须先更新可见性，再更数值
        updateCubeAxesActor(m_cubeAxesSetting->getVisibility());
        m_render3D->ResetCamera();
        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_graphNameDoubleClicked(QListWidgetItem* item)
    {
        InfomationGraph3DBasical* info = getInfoFromSidebarNameItem(item);
        if (info == nullptr) return;
        for (auto i : m_graphInfoList)
        {
            if (i == info)
            {
                auto tmp = info->m_fieldScalarBarGenerator->getLookupTable()->GetRange();
                i->m_threeDCloudMapSettingData->getScalarBarSettingData()->setScalarBarMinValue(tmp[0]);
                i->m_threeDCloudMapSettingData->getScalarBarSettingData()->setScalarBarMaxValue(tmp[1]);
                m_mainSettingDialog->updateSettingDataToUI(i->m_threeDCloudMapSettingData, ThreeDCloudMapSettingDialog::EntryType::ScalarBar);
                m_mainSettingDialog->updateSettingDataToUI(i->m_threeDCloudMapSettingData, ThreeDCloudMapSettingDialog::EntryType::ResultData);
            }
        }
        m_mainSettingDialog->execWindow();
    }

    void ThreeDCloudMapWindow::slot_getSidebarCurveDataSource(QListWidgetItem* item, QString& dataSource)
    {
        InfomationGraph3DBasical* info = getInfoFromSidebarNameItem(item);
        if (info != nullptr)
        {
            emit IWidgetSignalInstance->signal_getTwoDDataSources(static_cast<TextFileParser*>(info->m_reader), dataSource);
        }
    }

    bool ThreeDCloudMapWindow::computeSlicePositionEnum(
        InfomationGraph3DBasical* info, ThreeDCloudMapSidebarData* sidebarData)
    {
        //// 计算切片位置枚举值
        //QList<double> xSliceEnum;
        //QList<double> ySliceEnum;
        //QList<double> zSliceEnum;

        //ResultDataPointer dataResult = info->m_resultData;
        //if (dataResult == nullptr)
        //{
        //    m_errorMessage = "Compute slice position enum error!";
        //    return false;
        //}
        //ResultFilePointer resultFileInfo = dataResult->resultFileInfo.toStrongRef();
        //if (resultFileInfo == nullptr)
        //{
        //    m_errorMessage = "Compute slice position enum error!";
        //    return false;
        //}

        //auto sample_info = resultFileInfo->field_monitor_sample_info;
        //if (sample_info.num_x == 0 || sample_info.num_y == 0 || sample_info.num_z == 0)
        //{
        //    m_errorMessage = "Sample count is zero!";
        //    return false;
        //}

        //double spaceX = sample_info.num_x == 1 ? 0 : (sample_info.end_x - sample_info.sta_x) / (sample_info.num_x - 1);
        //double spaceY = sample_info.num_y == 1 ? 0 : (sample_info.end_y - sample_info.sta_y) / (sample_info.num_y - 1);
        //double spaceZ = sample_info.num_z == 1 ? 0 : (sample_info.end_z - sample_info.sta_z) / (sample_info.num_z - 1);

        //for (int i = 0; i < sample_info.num_x; ++i)
        //{
        //    xSliceEnum.append(sample_info.sta_x + i * spaceX);
        //}
        //for (int i = 0; i < sample_info.num_y; ++i)
        //{
        //    ySliceEnum.append(sample_info.sta_y + i * spaceY);
        //}
        //for (int i = 0; i < sample_info.num_z; ++i)
        //{
        //    zSliceEnum.append(sample_info.sta_z + i * spaceZ);
        //}

        auto nearFieldGraphGenerator = info->m_nearFieldDataGenerator;
        if (nearFieldGraphGenerator == nullptr)
        {
            m_errorMessage = "Compute slice position enum error!";
            return false;
        }
        QList<double> xSliceEnum = nearFieldGraphGenerator->GetXSlicePositionEnum();
        QList<double> ySliceEnum = nearFieldGraphGenerator->GetYSlicePositionEnum();
        QList<double> zSliceEnum = nearFieldGraphGenerator->GetZSlicePositionEnum();
        sidebarData->setXSliceEnum(xSliceEnum);
        sidebarData->setYSliceEnum(ySliceEnum);
        sidebarData->setZSliceEnum(zSliceEnum);
        sidebarData->setXSliceUnit(nearFieldGraphGenerator->GetXSlicePositionUnit());
        sidebarData->setYSliceUnit(nearFieldGraphGenerator->GetYSlicePositionUnit());
        sidebarData->setZSliceUnit(nearFieldGraphGenerator->GetZSlicePositionUnit());

        return true;
    }

    void ThreeDCloudMapWindow::generateSidebarSettingData(
        QListWidgetItem* item, InfomationGraph3DBasical* info)
    {
        ThreeDCloudMapSidebarData* sideBarData = new ThreeDCloudMapSidebarData(this);
        computeSlicePositionEnum(info, sideBarData);
        sideBarData->setCurrentShowType(0);
        sideBarData->setCurrentFixedParamIndex(0);

        TextFileParser* reader = static_cast<TextFileParser*>(info->m_reader);
        if (reader == nullptr)
        {
            return;
        }
        QVector<QString> valueNames = reader->getEachColGroupNameOfValue();
        sideBarData->setTextFileParser(reader);
        sideBarData->setValueGroupNameList(valueNames.toList());
        sideBarData->setCurrentValueGroupNameIndex(info->m_valueGroupNameIndex);
        sideBarData->setCurrentComponentIndex(info->m_valueComponentIndex);
        sideBarData->setDataSource(info->m_dataSources);

        info->m_TDCMSidebarData = sideBarData;

        auto graphName = generateGraphNameAuto(info);
        sideBarData->setGraphName(graphName);
        sideBarData->setIsGraphNameRenamed(false);
    }

    void ThreeDCloudMapWindow::connectSignalsAndSlots()
    {
        this->m_renderWindow3D->GetInteractor()->AddObserver(vtkCommand::LeftButtonDoubleClickEvent, m_doubleClickCallback);
    }

    void ThreeDCloudMapWindow::disconnectSignalsAndSlots()
    {
        this->m_renderWindow3D->GetInteractor()->RemoveObservers(vtkCommand::LeftButtonDoubleClickEvent);
    }

    void ThreeDCloudMapWindow::prepareAnimationData()
    {
        // 准备数据
        // if (!m_isAnimationDataPrepared)
        //{

        for (auto info : m_graphInfoList)
        {
            auto reader = static_cast<TextFileParser*>(info->m_reader);
            if (reader == nullptr)
            {
                qDebug() << "Error:" << __FILE__ << " " << __func__ << " " << __LINE__ << " TextFileParser reader is nullptr!";
                continue;
            }
            QList<TextFileParser*> readerList = static_cast<TextFileParser*>(reader)->GetOtherList();
            auto table = reader->getStandardTable();
            //auto sidebarData = info->m_threeDCloudMapSidebarData;
            //if (sidebarData == nullptr)
            //{
            //    qDebug() << "Error:" << __FILE__ << " " << __func__ << " " << __LINE__ << " sidebarData is nullptr!";
            //    continue;
            //}
            auto nearFieldDataGenerator = info->m_nearFieldDataGenerator;
            auto fieldGraphGenerator = info->m_fieldGraphGenerator;
            // if (!sidebarData->getIsShowActor())//不显示actor的话，不需要准备数据
            //{
            //     continue;
            // }

            auto sidebarData = info->m_TDCMSidebarData;
            auto valueIndex = sidebarData->getCurrentValueGroupNameIndex();
            auto parser = sidebarData->getTextFileParser();
            auto compIndex = sidebarData->getCurrentComponentIndex();

            int realIndex = parser->getRealValueIndex(valueIndex, compIndex);
            auto meta = parser->getDataInfoByRealValueIndex(realIndex);
            bool _isLog = false;
            if (meta.resultDataType == 2 || meta.resultDataType == 4)//幅度或标量采用界面设置的log
            {
                _isLog = sidebarData->getIsLog();
            }

            info->m_animationDataList.clear();
            info->m_animationTableList.clear();
            for (const auto& everyReader : readerList)
            {
                // 只需要更新数据源即可，其他的设置已经在slot_updateShowType进行更新
                nearFieldDataGenerator->setInputData(everyReader->getStandardTable());
                nearFieldDataGenerator->setLogTheData(_isLog);
                nearFieldDataGenerator->setNormalizeTheData(sidebarData->getIsNormalized());

                nearFieldDataGenerator->update(realIndex);
                auto dataset = nearFieldDataGenerator->getOutputData();

                auto resultTable = nearFieldDataGenerator->getResultTable();
                info->m_animationTableList.append(resultTable);

                vtkNew<vtkStructuredGrid> data;
                data->DeepCopy(dataset);
                m_allAnimationdData.append(data); // 保存所有的动画数据
                info->m_animationDataList.append(data);
            }

            // 恢复初始状态
            nearFieldDataGenerator->setInputData(reader->getStandardTable());
            nearFieldDataGenerator->setLogTheData(_isLog);
            nearFieldDataGenerator->setNormalizeTheData(sidebarData->getIsNormalized());
            info->m_currentAnimationIndex = readerList.indexOf(reader);
            nearFieldDataGenerator->update(realIndex);

            m_imageSize < info->m_animationDataList.size() ? m_imageSize = info->m_animationDataList.size() : m_imageSize = m_imageSize;
        }

        // m_isAnimationDataPrepared = true;
        //}
    }

    void ThreeDCloudMapWindow::updateControlPanel()
    {
        auto chosenItems = m_sidebarSettings->getCurveNameListWidget()->selectedItems();
        if (chosenItems.isEmpty())
        {
            return;
        }
        // ThreeDSurfacePlotSidebarData* data = m_sideBarSettingData.value(chosenItems.at(0));
        // m_sidebarSettings->updateInfoValueToUI(data);
    }

    void ThreeDCloudMapWindow::animationToNextDataFrame()
    {

        for (auto info : m_graphInfoList)
        {
            auto fieldGraphGenerator = info->m_fieldGraphGenerator;
            if (fieldGraphGenerator == nullptr)
            {
                continue;
            }
            auto& currentFrameID = info->m_currentAnimationIndex;

            if (m_isFirstTimeDataAnimation)//第一次进行数据动图时，始终播放第一帧
            {
                currentFrameID = 0;
                m_isFirstTimeDataAnimation = false;
            }
            else
            {
                int tempID = currentFrameID + m_animationSettingData->sampleRate();
                currentFrameID = tempID >= info->m_animationDataList.size() ? 0 : tempID;
            }
            if (m_isBeginExportAnimation)//是从导出动图启动，始终播放第一帧
            {
                currentFrameID = 0;
                m_isBeginExportAnimation = false;
                m_animationDataCount = 0;
            }
            qDebug() << "currentFrameID: " << currentFrameID;
            fieldGraphGenerator->SetInputDataSet(info->m_animationDataList.at(currentFrameID));

            // 更新info存储的reader和path信息
            // 将当前帧数据设置回info 
            TextFileParser* _reader = static_cast<TextFileParser*>(info->m_reader)->GetOtherList().at(currentFrameID);
            info->m_reader = _reader;
            info->m_nearFieldDataGenerator->setInputData(static_cast<TextFileParser*>(info->m_reader)->getStandardTable());
            info->m_tableToExport = info->m_animationTableList[currentFrameID];
            info->m_geometryFileName = _reader->GetGeometryFileName();
            info->m_filePath = _reader->GetFileName();

            // 更新频率
            // auto freList = info->m_farFieldDataGenerator->getFreqencyList();
            // info->m_currentFrequency = info->m_farFieldDataGenerator->getFreqencyList()[currentFrameID];
            // auto item = m_curveMap.key(info);
            // auto sideBarData = m_sideBarSettingData.value(item);
            // sideBarData->setCurrentFrequency(info->m_currentFrequency);

            // const auto& currentField = info->m_currentScalarArray;
            int groupValueIndex = info->m_valueGroupNameIndex;
            int componentValueIndex = info->m_valueComponentIndex;
            auto reader = static_cast<TextFileParser*>(info->m_reader);
            int realIndex = reader->getRealValueIndex(groupValueIndex, componentValueIndex);

            auto isSetSuccess = fieldGraphGenerator->SetActiveScalarAttribute(
                realIndex, FieldGraphGenerator::StructureType::POINTS, 0);
            if (!isSetSuccess)
            {
                return;
            }
            fieldGraphGenerator->UpdateScalarFieldActor();
            updateControlPanel();

            //更新数据源
            auto item = info->m_sidebarItem;
            QString dataSource;
            slot_getSidebarCurveDataSource(item, dataSource);
            auto data = info->m_TDCMSidebarData;
            data->setDataSource(dataSource);

            //更新结果数据组名
            data->setValueGroupNameList(_reader->getEachColGroupNameOfValue().toList());

            if (item->isSelected())
            {
                m_sidebarSettings->updateInfoDataAndInterfaceToUI(data);
                m_sidebarSettings->setControlPanelEditable(false);
            }

            sentToolBarAnimationDataInfo(info);
        }
        qDebug() << "currentFrameID:=========== ";

        updateMarkerValue();
        updateCubeAxesActor(m_cubeAxesSetting->getVisibility());
        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_addCustomContextMenu(const QPoint& pos)
    {
        QMenu contextMenu(this);

        // 添加主菜单项
        // QMenu* addMarkerMenu = contextMenu.addMenu("添加标记点");
        if (!m_isAddingPointMarker)
        {
            if (!m_graphInfoList.isEmpty())
            {
                QAction* addPointMarker = contextMenu.addAction("添加标记");
                QObject::connect(addPointMarker, &QAction::triggered, this, &Graph3DWindowBase::slot_beginAddPointMarker);
            }
        }
        else
        {
            QAction* stopAddMarkerMenu = contextMenu.addAction("退出标记模式");
            QObject::connect(stopAddMarkerMenu, &QAction::triggered, this, &Graph3DWindowBase::slot_stopAddMarker);
        }
        // QAction* addCellMarker = addMarkerMenu->addAction("添加面标记");

        int selectedRowCount = m_markerDataTable->getInnerTableWidget()->selectedItems().size();
        QAction* deleteChosenMarker = contextMenu.addAction("删除选中标记");
        deleteChosenMarker->setEnabled(selectedRowCount > 0);

        int rowCount = m_markerDataTable->getInnerTableWidget()->rowCount();
        QAction* deleteAllMarkers = contextMenu.addAction("删除所有标记");
        deleteAllMarkers->setEnabled(rowCount > 0);
        QAction* exportTableData = contextMenu.addAction("导出标记数据");
        exportTableData->setEnabled(rowCount > 0);

        // QObject::connect(addCellMarker, &QAction::triggered, this, &Graph3DWindowBase::slot_beginAddCellMarker);
        QObject::connect(deleteChosenMarker, &QAction::triggered, this, &Graph3DWindowBase::slot_removeChosenMarker);
        QObject::connect(deleteAllMarkers, &QAction::triggered, this, &Graph3DWindowBase::slot_removeAllMarker);
        QObject::connect(exportTableData, &QAction::triggered, this, &Graph3DWindowBase::slot_exportTableData);

        contextMenu.exec(m_qvtkWidget->mapToGlobal(pos));
    }

    void ThreeDCloudMapWindow::updateMarkerVisibility()
    {
        auto markerWidget = m_markerDataTable->getInnerTableWidget();

        for (const auto& graphInfo : m_graphInfoList)
        {

            // 与 graphInfo 的sourceActor相同的进行处理
            // 显示类型为0，则直接与sourceActor是否显示一致,其他显示类型不显示
            // 显示类型不为0，则为0的不显示，slicePosition也一致的与sourceActor是否显示一致，其他显示类型不显示
            auto item = graphInfo->m_sidebarItem;
            auto sidebarData = graphInfo->m_TDCMSidebarData;

            auto sourceActor = graphInfo->m_actor;
            auto showType = sidebarData->getCurrentShowType();
            auto slicePosition = sidebarData->getCurrentFixedParamIndex();
            bool visibility = false;

            for (int rowIndex = 0; rowIndex < markerWidget->rowCount(); ++rowIndex)
            {
                auto markerId = markerWidget->item(rowIndex, 0)->text().toInt();
                auto markerInfo = m_marker3DDataInfoList.value(markerId);
                if (markerInfo == nullptr)
                {
                    qDebug() << __FILE__ << " " << __LINE__ << " Marker info is nullptr!";
                    continue;
                }
                auto markerSourceActor = markerInfo->m_sourceActor;
                auto markerSourceActorType = markerInfo->m_showType;
                auto markerSourceActorTypefixedParam = markerInfo->m_fixedParamIndex;

                if (m_isActiveClip)
                {
                    double* markerPosition = markerInfo->m_markerPosition;
                    bool isInside = CommonFunction::isPointKeptByPlane(markerPosition[0], markerPosition[1], markerPosition[2],
                        m_planeOrigin[0], m_planeOrigin[1], m_planeOrigin[2], m_planeNormalDirection[0], m_planeNormalDirection[1], m_planeNormalDirection[2]);
                    visibility = isInside && sourceActor->GetVisibility();
                }
                else
                {
                    visibility = sourceActor->GetVisibility();
                }

                if (markerSourceActor != sourceActor)
                {
                    continue;
                }
                if (showType == 0 && markerSourceActorType == 0)
                {
                    markerWidget->setRowHidden(rowIndex, !visibility);
                    markerInfo->m_markerActor->SetVisibility(visibility);
                    markerInfo->m_markerTextActor->SetVisibility(visibility);
                }
                else if (showType == markerSourceActorType && slicePosition == markerSourceActorTypefixedParam)
                {
                    markerWidget->setRowHidden(rowIndex, !visibility);
                    markerInfo->m_markerActor->SetVisibility(visibility);
                    markerInfo->m_markerTextActor->SetVisibility(visibility);
                }
                else
                {
                    markerWidget->setRowHidden(rowIndex, true);
                    markerInfo->m_markerActor->SetVisibility(false);
                    markerInfo->m_markerTextActor->SetVisibility(false);
                }
            }
        }

        markerWidget->setColumnHidden(0, true); // 仍然隐藏markerId列

        updatePickedDataDisplayWindowVisibility();
    }

    void ThreeDCloudMapWindow::removeActorWithMarker(InfomationGraph3DBasical* info)
    {
        FieldGraphGenerator* fieldGraphGenerator = info->m_fieldGraphGenerator;
        if (fieldGraphGenerator == nullptr)
        {
            qDebug() << "Error: " << __FILE__ << " " << __LINE__ << " Chosen data's generator not exist!";
            return;
        }
        auto actor = fieldGraphGenerator->GetScalarsFieldActor();
        auto scalarBaractor = info->m_scalarBar;
        auto scalarBarWidget = info->m_fieldScalarBarGenerator->getScalarBarWidget();
        info->m_fieldScalarBarGenerator->removeAGraph(fieldGraphGenerator);
        //auto clipperGerator = info->m_dataClipperGenerator;
        QList<Marker3DDataInfo*> toDeleteList;
        QList<int> toDeleteTableIndexs;
        auto innerMatrkerTable = m_markerDataTable->getInnerTableWidget();

        for (const auto& i : m_marker3DDataInfoList)
        {
            if (i->m_sourceActor == actor)
            {
                m_render3D->RemoveActor(i->m_markerActor);
                m_render3D->RemoveActor(i->m_markerTextActor);

                // 同步markerTable可见性
                for (int row = 0; row < innerMatrkerTable->rowCount(); ++row)
                {
                    if (innerMatrkerTable->item(row, 0)->text().toInt() == i->m_markerId)
                    {
                        toDeleteTableIndexs.append(row);
                    }
                }
                toDeleteList.append(i);
            }
        }
        for (const auto& i : toDeleteList)
        {
            int key = m_marker3DDataInfoList.key(i);
            m_marker3DDataInfoList.remove(key);
        }
        std::sort(toDeleteTableIndexs.begin(), toDeleteTableIndexs.end());
        for (int i = toDeleteTableIndexs.size() - 1; i >= 0; --i)
        {
            innerMatrkerTable->removeRow(toDeleteTableIndexs.at(i));
        }
        if (innerMatrkerTable->rowCount() == 0)
        {
            m_markerDataTable->hide();
        }
        m_render3D->RemoveActor(actor);

        bool leftSameType = false;//是否还有同类型的actor存在
        for (auto i : m_graphInfoList)
        {
            if (i == info)
            {
                continue;
            }

            //判断类型是否相同
            if (info->m_resultType == i->m_resultType)
            {
                leftSameType = true;
                break;
            }
        }

        if (!leftSameType)
        {
            m_render3D->RemoveActor(scalarBaractor);
            scalarBarWidget->SetEnabled(false);
        }

        qDebug() << "info->m_scalarBar = " << info->m_scalarBar;
        //if (clipperGerator != nullptr)
        //{
        //    m_render3D->RemoveActor(clipperGerator->getClipActor());
        //}
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::updateMarkerValue()
    {
        auto tableWidget = m_markerDataTable->getInnerTableWidget();
        for (int i = 0; i < tableWidget->rowCount(); ++i)
        {
            // 不显示的不更新，不显示包括（可见性为false和显示类型不同）
            // 因此更新actor可见性时，需要调用本函数
            if (tableWidget->isRowHidden(i))
            {
                continue;
            }

            int markerId = tableWidget->item(i, 0)->text().toInt();

            Marker3DDataInfo* markerInfo = m_marker3DDataInfoList.value(markerId);
            if (markerInfo == nullptr)
            {
                continue;
            }

            auto dataSet = markerInfo->m_sourceActor->GetMapper()->GetInput();
            if (!dataSet)
            {
                return;
            }

            auto curveNameWidget = m_sidebarSettings->getCurveNameListWidget();
            for (int row = 0; row < curveNameWidget->count(); ++row)
            {
                QListWidgetItem* item = curveNameWidget->item(row);
                auto graphInfo = getInfoFromSidebarNameItem(item);
                //FieldGraphGenerator::ArrayInformation currentArray = graphInfo->m_currentScalarArray;

                auto reader = static_cast<TextFileParser*>(graphInfo->m_reader);
                int groupValueIndex = graphInfo->m_valueGroupNameIndex;
                int componentValueIndex = graphInfo->m_valueComponentIndex;
                int realIndex = reader->getRealValueIndex(groupValueIndex, componentValueIndex);
                auto valueNames = reader->getEachColNameOfValue();
                QString arrayName = valueNames[realIndex];

                if (graphInfo->m_actor != markerInfo->m_sourceActor) //|| realIndex != markerInfo->m_fieldIndex)
                {
                    continue;
                }
                auto sideBarData = graphInfo->m_TDCMSidebarData;
                if (sideBarData->getCurrentShowType() == 0)
                {
                    if(markerInfo->m_showType!=0)
                    {
                        continue;
                    }
                }
                else if (sideBarData->getCurrentShowType() != markerInfo->m_showType) //切片模式
                {
                    continue;
                }
                else if(sideBarData->getCurrentFixedParamIndex()!=markerInfo->m_fixedParamIndex)
                {
                    continue;
                }

                if (markerInfo->m_markerType == 0) //云图只有点拾取
                {
                    //auto activeArray = dataSet->GetPointData()->GetScalars();
                    auto activeArray = graphInfo->m_fieldGraphGenerator->getUsingData()->GetPointData()->GetScalars();
                    QString pickedValue = "null";
                    if (activeArray != nullptr) // 原数据有激活point场
                    {
                        if (markerInfo->m_pickedId < graphInfo->m_fieldGraphGenerator->getUsingData()->GetNumberOfPoints())
                        {
                            double value = activeArray->GetComponent(markerInfo->m_pickedId, 0);
                            pickedValue = QString::number(value);

                            tableWidget->item(i, 4)->setText(QString::number(value));
                            tableWidget->item(i, 2)->setText(activeArray->GetName());
                            markerInfo->m_markerValue = value;
                        }
                        else
                        {
                            qDebug() << "Error:currentPointId is out of range";
                        }
                    }
                }
            }
        }
    }

    bool ThreeDCloudMapWindow::isInfoContainsMultipleData(const InfomationGraph3DBasical* info)
    {
        auto reader = info->m_reader;
        if (reader == nullptr)
        {
            return false;
        }
        // 将当前帧数据设置回info
        auto readerList = static_cast<TextFileParser*>(info->m_reader)->GetOtherList();

        return readerList.size() > 1;
    }

    bool ThreeDCloudMapWindow::isInfoFromSameSource(QList<InfomationGraph3DBasical*> infoList)
    {
        if (infoList.isEmpty())
        {
            return false;
        }

        QString _folderPath{ "" };
        int count = 0;
        for (const auto& info : infoList)
        {
            QString filePath = info->m_filePath;
            QFileInfo fileInfo(filePath);
            QString folderPath = fileInfo.absolutePath();

            if (folderPath.isEmpty())
            {
                return false;
            }

            if (count == 0)
            {
                _folderPath = folderPath;
                ++count;
                continue;
            }

            if (folderPath != _folderPath)
            {
                return false;
            }
        }
        return true;
    }

    bool ThreeDCloudMapWindow::whetherCanEnableDataAnimation()
    {
        if (m_graphInfoList.size() != 1)
        {
            return false;
        }

        return isInfoContainsMultipleData(m_graphInfoList[0]) ? true : false;
    }

    void ThreeDCloudMapWindow::setFrameToBeforeExportAnimation()
    {
        for (auto info : m_graphInfoList)
        {

            for (int i = 0; i < info->m_animationDataList.size(); ++i)
            {
                qDebug() << "pointer " << i << " = " << info->m_animationDataList[i];
            }

            auto fieldGraphGenerator = info->m_fieldGraphGenerator;
            fieldGraphGenerator->SetInputDataSet(info->m_animationDataList.at(info->m_lastFrameIndexBeforeExportAnimation));
            info->m_currentAnimationIndex = info->m_lastFrameIndexBeforeExportAnimation;
            if (info->m_valueGroupNameIndex != -1)
            {
                int groupValueIndex = info->m_valueGroupNameIndex;
                int componentValueIndex = info->m_valueComponentIndex;
                auto reader = static_cast<TextFileParser*>(info->m_reader);
                int realIndex = reader->getRealValueIndex(groupValueIndex, componentValueIndex);

                auto isSetSuccess = fieldGraphGenerator->SetActiveScalarAttribute(
                    realIndex, FieldGraphGenerator::StructureType::POINTS, 0);
                if (!isSetSuccess)
                {
                    return;
                }
                fieldGraphGenerator->UpdateScalarFieldActor();
            }
            else
            {
                fieldGraphGenerator->UpdateGeometryActor();
            }
            sentToolBarAnimationDataInfo(info);
        }
        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::sentToolBarAnimationDataInfo(const InfomationGraph3DBasical* info)
    {
        auto& currentFrameID = info->m_currentAnimationIndex;

        //右上角显示动图信息
        auto _type = info->m_fieldType;
        auto unit = info->m_unit;
        auto varValueList = info->m_VarValueList;

        QString typeString{};

        if (m_animationType == 0)//数据变换
        {
            if (_type == 1)
            {
                typeString = "时间";
            }
            else if (_type == 2)
            {
                typeString = "频率";//三维曲面图数据变化始终是频率
            }
        }
        else //相机
        {
            typeString = "角度";
            unit = "deg";
        }

        //TODO 拿到变量名称
        auto currentValue = varValueList[currentFrameID];
        QString firstLine = typeString + ": " + QString::number(currentValue) + " " + unit;

        auto sameRate = m_animationSettingData->sampleRate();
        QString secondLine = "采样率: " + QString::number(sameRate);

        auto frameRate = m_animationSettingData->frameRate();
        QString thirdLine = "播放速度: " + QString::number(frameRate);

        QStringList textActorList;
        textActorList << firstLine << secondLine << thirdLine;
        setAnimationInfoText(textActorList);

        int totalNum = std::ceil(double(info->m_animationDataList.size()) / sameRate);

        if (m_animationDataCount * sameRate >= info->m_animationDataList.size())
        {
            m_animationDataCount = 0;
        }

        if (m_animationTooBarInfoData != nullptr)
        {
            m_animationTooBarInfoData->setType(typeString);
            m_animationTooBarInfoData->setUnit(unit);
            m_animationTooBarInfoData->setCurrentValue(QString::number(currentValue));
            m_animationTooBarInfoData->setSliderCurrentValue(currentFrameID);
            m_animationTooBarInfoData->setSliderMaxValue(totalNum);
        }

        emit IWidgetSignalInstance->signal_setToolBarAnimationDataInfo(typeString, unit, currentValue, totalNum, m_animationDataCount);
        ++m_animationDataCount;
    }

    QString ThreeDCloudMapWindow::generateGraphNameAuto(InfomationGraph3DBasical* info) const
    {
        QString graphName;

        auto fileType = info->m_resultType;
        auto graphId = info->m_graphIDFromType;

        auto groupIndex = info->m_valueGroupNameIndex;
        auto compIndex = info->m_valueComponentIndex;
        auto parser = static_cast<TextFileParser*> (info->m_reader);
        if (parser == nullptr)
        {
            return graphName;
        }
        auto realValueIndex = parser->getRealValueIndex(groupIndex, compIndex);
        auto metaInfo = parser->getDataInfoByRealValueIndex(realValueIndex);
        auto groupName= metaInfo.dataGroupName;
        auto compoType = metaInfo.resultDataType;

        QString arrayName;
        switch (compoType)//0:实部, 1 : 虚部, 2 : 幅度, 3 : 相位 4 : 标量
        {
        case 0:
            arrayName = "Re("+ groupName+")";
            break;
        case 1:
            arrayName = "Im(" + groupName + ")";
            break;
        case 2:
            arrayName = "mag(" + groupName + ")";
            break;
        case 3:
            arrayName = "arg(" + groupName + ")";
            break;
        case 4:
            arrayName = groupName;
            break;
        }

        auto typeString = GetResultDataTypeAsString(fileType, false);
        if (arrayName.isEmpty())
        {
            graphName = typeString + "_" + QString::number(graphId);
        }
        else
        {
            graphName = typeString + "_" + QString::number(graphId) + "[" + arrayName + "]";
        }
        return graphName;
    }


    ThreeDCloudMapSettingData* ThreeDCloudMapWindow::getMainSettingData(InfomationGraph3DBasical* info)
    {
        for (auto i : m_graphInfoList)
        {
            if (i == info)
            {
                return i->m_threeDCloudMapSettingData;
            }
        }
    }


    ThreeDCloudMapSidebarData* ThreeDCloudMapWindow::getSidebarDataFromNameItem(QListWidgetItem* item)
    {
        for (auto info : m_graphInfoList)
        {
            if (info->m_sidebarItem == item)
            {
                return info->m_TDCMSidebarData;
            }
        }
        return nullptr;
    }

    InfomationGraph3DBasical* ThreeDCloudMapWindow::getGraph3DInfoFromSidebarData(ThreeDCloudMapSidebarData* data)
    {
        for (auto info : m_graphInfoList)
        {
            if (info->m_TDCMSidebarData == data)
            {
                return info;
            }
        }
        return nullptr;
    }

    void ThreeDCloudMapWindow::updateGeometryActors(bool isShow, bool& hasAnyGeometrySuccess)
    {
        bool _hasAnyGeometry = false;
        m_isShowingGeometry = isShow;
        QList<QStringList> m_updatedList;

        for (auto info : m_graphInfoList)
        {
            const auto& path = info->m_geometryFileName;
            if (path.empty())
            {
                continue;
            }

            if (isShow)
            {
                if (m_updatedList.contains(path))
                {
                    continue;
                }

                //if (info->m_geomtryActorGenerator == nullptr)
                //{
                //    GeomtryActorGenerator* generator = new GeomtryActorGenerator(this);
                //    generator->setFileNameList(path);
                //    //generator->setIsActiveClip(m_isActiveClip);
                //    //generator->setClipPlaneNormalDirection(m_planeNormalDirection);
                //    //generator->setClipPlaneOrigin(m_planeOrigin);
                //    //generator->updateActor();
                //    info->m_geomtryActorGenerator = generator;
                //    //info->m_geometryActor = generator->getActor();
                //    m_render3D->AddActor(generator->getActor());
                //}

                m_updatedList.append(path);

                info->m_geomtryActorGenerator->setIsActiveClip(m_isActiveClip);
                info->m_geomtryActorGenerator->setClipPlaneNormalDirection(m_planeNormalDirection);
                info->m_geomtryActorGenerator->setClipPlaneOrigin(m_planeOrigin);
                int status = info->m_geomtryActorGenerator->updateActor();
                if (status == 2)//全部失败的情况
                {
                    //QString _errorText = info->m_geomtryActorGenerator->getErrorMessage();
                    //emit IBaseSignalInstance->signal_sendErrorMessageToUI(_errorText);
                    //delete info->m_geomtryActorGenerator;
                    //info->m_geomtryActorGenerator = nullptr;
                    continue;
                }
                //else if (status == 1)//部分失败的情况，继续执行
                //{
                //    QString _errorText = info->m_geomtryActorGenerator->getErrorMessage();
                //    emit IBaseSignalInstance->signal_sendErrorMessageToUI(_errorText);
                //}

                auto centerSetting = getMainSettingData(info);
                int tranceparency = centerSetting->getGeometrySettingData()->getGeometryTransparency();

                if (tranceparency == 100)//全部透明的情况
                {
                    info->m_geomtryActorGenerator->getActor()->SetVisibility(false);

                }
                else
                {
                    info->m_geomtryActorGenerator->getActor()->SetVisibility(true);
                }

                m_render3D->AddActor(info->m_geomtryActorGenerator->getActor());
                _hasAnyGeometry = true;
            }
            else
            {
                if (info->m_geomtryActorGenerator != nullptr)
                {
                    info->m_geomtryActorGenerator->getActor()->SetVisibility(0);
                    _hasAnyGeometry = true;
                }
            }
        }

        if (isShow && !_hasAnyGeometry)//全部失败的情况
        {
            emit IBaseSignalInstance->signal_sendErrorMessageToUI("未读取到有效几何文件");
            m_isShowingGeometry = false;//没有几何文件导入成功的情况下，要将显示状态设为false,同时显示模型的按钮设置为未选中
        }
        hasAnyGeometrySuccess = _hasAnyGeometry;

        m_render3D->ResetCameraClippingRange();
        m_renderWindow3D->Render();
    }

    void ThreeDCloudMapWindow::slot_renameCheck()
    {
        auto listWidget = m_sidebarSettings->getCurveNameListWidget();
        auto selectedItems = listWidget->selectedItems();
        if (selectedItems.size() != 1)
        {
            return;
        }
        auto item = selectedItems[0];
        auto info = getInfoFromSidebarNameItem(item);
        //auto graph = qobject_cast<QCPGraph*>(info->getCurveLineAddress());

        if (item->text().isEmpty())
        {
            EDialogMsgResult _result = IdaDialogMsg::showDialog(this, QString("命名不能为空，请重新编辑。"), EDialogMsg::Error, tr("重命名错误"));
            item->setText(info->m_name);
            return;
        }

        for (auto i : m_graphInfoList)
        {
            auto tmpItem = i->m_sidebarItem;
            if (tmpItem == item)
            {
                continue;
            }
            if (item->text() == tmpItem->text())
            {
                EDialogMsgResult _result = IdaDialogMsg::showDialog(this, QString("当前名称已存在，请重新编辑。"), EDialogMsg::Error, tr("重命名错误"));
                item->setText(info->m_name);
                return;
            }
        }
        info->m_isGraphRenamed = true;
        synchronousActorName(info, item->text());

        QStringList _pyCodes{};
        QString newName = "'" + item->text() + "'";
        _pyCodes += QString("threedcloudmapsidebarsettings8 = PostProcessing.ThreeDCloudMapSidebarSettingsPy()");
        _pyCodes += QString("threedcloudmapsidebarsettings8.nameItemRename(%1,%2,%3)").arg(m_windowId).arg(listWidget->row(item)).arg(newName);
        emit IBaseSignalInstance->signal_execPYCode(_pyCodes, true, false);
    }

    bool ThreeDCloudMapWindow::slot_checkResultNameIsValid(ThreeDCloudMapSettingData* data, const QString& newName)
    {
        if (newName.isEmpty())
        {
            EDialogMsgResult _result = IdaDialogMsg::showDialog(this, QString("命名不能为空，请重新编辑。"), EDialogMsg::Error, tr("重命名错误"));
            return false;
        }

        for (auto i : m_graphInfoList)
        {
            if (i->m_threeDCloudMapSettingData == data)
            {
                continue;
            }
            if (i->m_threeDCloudMapSettingData->getResultDataSettingData()->getResultDataName() == newName)
            {
                EDialogMsgResult _result = IdaDialogMsg::showDialog(this, QString("当前名称已存在，请重新编辑。"), EDialogMsg::Error, tr("重命名错误"));
                return false;
            }
        }

        for (auto i : m_graphInfoList)
        {
            if (i->m_threeDCloudMapSettingData == data && i->m_name != newName)//是重命名
            {
                i->m_isGraphRenamed = true;
                break;
            }
        }

        return true;

    }

    void ThreeDCloudMapWindow::synchronousActorName(InfomationGraph3DBasical* info, const QString& newName)
    {
        if (info == nullptr)
        {
            return;
        }

        auto item = info->m_sidebarItem;
        if (item == nullptr)
        {
            return;
        }

        QSignalBlocker bl(m_sidebarSettings->getCurveNameListWidget());
        item->setText(newName);
        item->setToolTip(newName);

        info->m_name = newName;

        auto sidebarSetting = info->m_TDCMSidebarData;
        if (sidebarSetting != nullptr)
        {
            sidebarSetting->setGraphName(newName);
            sidebarSetting->setIsGraphNameRenamed(true);
        }

        auto mainSetting = getMainSettingData(info);
        if (mainSetting != nullptr)
        {
            mainSetting->getResultDataSettingData()->setResultDataName(newName);
        }
    }

    void ThreeDCloudMapWindow::slot_closeTree(const QList<QStandardItem*>& items)
    {
        QList<QListWidgetItem*> itemToDelete;
        for (auto treeItem : items)
        {
            for (auto info : m_graphInfoList)
            {
                if (info->m_projectTreeSourceItem == treeItem)
                {
                    auto sidebarItem = info->m_sidebarItem;
                    itemToDelete.append(sidebarItem);
                }
            }
        }
        slot_deleteChosenGraphs(itemToDelete);
    }


    QHash<int, QString> ThreeDCloudMapWindow::getMarkerNameMap()
    {
        QHash<int, QString> map;
        auto table = m_markerDataTable->getInnerTableWidget();
        for (int i = 0; i < table->rowCount(); ++i)
        {
            QString markerName = table->item(i, 1)->text();
            map.insert(i, markerName);
        }
        return map;
    }

} // namespace pst
